package Problemas;
import Busquedas.Estado;

/**
 * Clase que representa el problema de laberinto. Extiende de la clase problema.
 *
 */
public class Laberinto extends Problema{

               private final static int ARRIBA = 0;

               private final static int DERECHA = 1;

               private final static int ABAJO = 2;

               private final static int IZQUIERDA = 3;

               private CasillaLaberinto matriz[][]; 

               int i;

               int j;



               /**
             * Constructor de clase.
             */
            public Laberinto(){
                       matriz = new CasillaLaberinto[6][7];
                       inicializaMatriz();
                       int paramInicial[]={3,0};
                       Estado inicial = new Estado(paramInicial);
                       int paramObjetivo[] = {3,6};
                       Estado objetivo[] = new Estado[1];
                       objetivo[0] = new Estado(paramObjetivo);
                       String [] nombresOperadores={"padre","arriba","derecha","abajo","izquierda"};
                       int [] costeOperadores={1,1,1,1};
                       inicializa(inicial,objetivo,4,nombresOperadores,costeOperadores);
               }

            
        	/**
        	 * asigna los parametros del estado dado.
        	 * @param e estado dado.
        	 */
               private void asignaParametros(Estado actual){
                       i = actual.getParametro(0);
                       j = actual.getParametro(1);
               }



               /**
             * Inicializa l�a matriz del problema
             */
            private void inicializaMatriz(){
                       matriz[0][0]=new CasillaLaberinto(1,0,0,1);
                       matriz[0][1]=new CasillaLaberinto(1,0,0,0);
                       matriz[0][2]=new CasillaLaberinto(1,1,0,0);
                       matriz[0][3]=new CasillaLaberinto(1,0,0,1);
                       matriz[0][4]=new CasillaLaberinto(1,1,0,0);
                       matriz[0][5]=new CasillaLaberinto(1,0,0,1);
                       matriz[0][6]=new CasillaLaberinto(1,1,0,0);
                       int i;
                       for (i = 0; i < matriz[1].length; i++)
                               matriz[1][i]=new CasillaLaberinto(0,1,0,1);
                       matriz[2][0] = new CasillaLaberinto(0,1,1,1);
                       for (i = 1; i < matriz[2].length; i++)
                               matriz[2][i] = new CasillaLaberinto(0,1,0,1);
                       matriz[3][0]=new CasillaLaberinto(1,0,0,0); //inicial
                       matriz[3][1]=new CasillaLaberinto(0,1,1,0);
                       matriz[3][2]=matriz[3][3] = matriz[3][4] = matriz[3][5] = new CasillaLaberinto(0,1,0,1);
                       matriz[3][6]=new CasillaLaberinto(0,0,0,1); //final
                       matriz[4][0]=new CasillaLaberinto(0,1,0,1);
                       matriz[4][1]=new CasillaLaberinto(1,0,1,1);
                       matriz[4][2]=new CasillaLaberinto(0,0,1,0);
                       matriz[4][3]=new CasillaLaberinto(0,1,1,0);
                       matriz[4][4]=new CasillaLaberinto(0,0,1,1);
                       matriz[4][5]=new CasillaLaberinto(0,1,1,0);
                       matriz[4][6]=new CasillaLaberinto(0,0,0,1);
                       matriz[5][0]=new CasillaLaberinto(0,0,1,1);
                       matriz[5][1]=matriz[5][2]=matriz[5][5]=new CasillaLaberinto(1,0,1,0);
                       matriz[5][3]=new CasillaLaberinto(1,1,1,0);
                       matriz[5][4]=new CasillaLaberinto(1,0,1,1);
                       matriz[5][6]=new CasillaLaberinto(0,1,1,0);
               }

            
               /**
             * @param direccion direccion que comprobamos
             * @return si hay muro ene sa direccion
             */
            private boolean hayMuro(int direccion){
                       return matriz[i][j].getMuro(direccion) == 1;
               }

            
               /**
                * mira si el limite es correcto
             * @return booleano deiciendo si es correcto
             */
            private boolean limiteCorrecto(){
                       return (i >= 0 && i <= 5 && j >= 0 && j <= 6);
               }


               /* (non-Javadoc)
             * @see Problema#aplicaOperador(Estado, int)
             */
            public Estado aplicaOperador(Estado actual,int operador){
                       asignaParametros(actual);
                       if (hayMuro(operador))
                               return null;
                       switch(operador){
                               case ARRIBA:
                                       i--;
                                       break;
                               case DERECHA:
                                       j++;
                                       break;
                               case ABAJO:
                                       i++;
                                       break;
                               case IZQUIERDA:
                                       j--;
                                       break;
                       }
                       if (limiteCorrecto()){
                               int []param = {i,j};
                               return new Estado(param);
                       }
                       return null;
               }

               /* (non-Javadoc)
             * @see Problema#getOperadorInverso(int)
             */
            @Override
               public int getOperadorInverso(int op) {
                       int inverso = -1;
                       switch(op){
                               case ARRIBA:
                                       inverso = ABAJO;
                                       break;
                               case DERECHA:
                                       inverso = IZQUIERDA;
                                       break;
                               case ABAJO:
                                       inverso = ARRIBA;
                                       break;
                               case IZQUIERDA:
                                       inverso = DERECHA;
                                       break;
                       }
                       return inverso;
               }

               //distancia desde la casilla en la que estas hasta la q buscas
               public int funcionHeuristica(Estado e){
            	   asignaParametros(e);
            	   return Math.abs(i-this.getObjetivo()[0].getParametro(0))+Math.abs((j-this.getObjetivo()[0].getParametro(1)));
            	  }
}
